/*-------------------------------------------------------------------------
*************************************************************************
* @doc PIP
* @module ifldtbl.c |
* The Field definition table.
*
* Product     :   SoftPay 2000 (Global Payment Methodology).
* <nl>Developer   : Monique Brown
* <nl>Notes       :
*
* @head3 PIP & ISO Functions |
* @index | PIP
* @end
*
* Copyright (c) 1996-2000 by VeriFone Inc. All rights reserved.
*
* No part of this software may be used, stored, compiled, reproduced,
* modified, transcribed, translated, transmitted, or transferred, in any form
* or by any means whether electronic, mechanical, magnetic, optical,
* or otherwise, without the express prior written permission of VeriFone, Inc.

$Log: /SoftPay/SPK2SIM/Source/PIP/ifldtbl.c $
--------------------------------------------------------------------------*/
#include <project.h>
#define IFLDTBL_C

#include <aclconio.h>
#include <stdio.h>
#include <stdlib.h>
#include <acldev.h>
#include <aclutil.h>
#include <message.h>
#include <aclstr.h>
#include <applidl.h>
#include <xmodem.h>
#include <iso8583.h>
#include <amexhost.h>
#include <string.h>
#include <dbmgr.h>

#ifdef PIP_DEFINED

/** /#define DEBUG_IFLDTBL*/
#ifdef DEBUG_IFLDTBL
#define DEBUG_95
#endif

#include <define.h>
#include <spdebug.h>
#include <ifldtbl.h>
#include <codesec.h>

ISO_DATA srISO;

/* Only the Private Field definitions and Host specific fields are defined
 * in the ISO module. The other fields are defined in the GDS.
 */

unsigned char Mti[MTI_SIZE];
unsigned char tpdu[TPDU_SIZE + 1];

unsigned char src_8583buf[ISO8583FLD_SIZE + 1];
unsigned char dst_8583buf[ISO8583FLD_SIZE + 1];

unsigned char* tsrc_8583;
unsigned char* tdst_8583;

unsigned char pszFieldROC[10];
unsigned char pszFieldDCP[23];
unsigned char szDiscard[2];
unsigned char stOptionalMap[BIT_MAP_SIZE];

/* Variant Tables initial definitions. Space is allocated in host specific
    code and the tables are loaded when the transactions are initiated
    The temp arrays are needed for the field table. Pointers in the
    field table produce compile errors. mb 4/11/97 */

variant_struct srTempVariant60[] = {
    { 93,   500,    36,      AV3_STR,    VARIABLE(srISO.pszField60) },

};
variant_struct srTempVariant63[] = {
    { 93,   500,    36,      AV3_STR,    VARIABLE(srISO.pszField63) },

};

variant_struct* psrVariant60;
variant_struct* psrVariant63;

field_struct srBaseIsoFDT[] = {
    /*  Fld.No  Packet Sz.  Cvt. Idx    Variable Nm.    Size */

    { 0,   10,  BCD_STR,  VARIABLE(tpdu)      },
    { 0,   16,  BIT_BIT,  VARIABLE(Mti)       },
    { 2,   19,  BV2_STR,  VARIABLE(srISO.pszField02)},
    { 3,   24,  BIT_BIT,  VARIABLE(srISO.pszField03)},
    { 4,   12,  BCD_SNZ,  VARIABLE(srISO.pszField04)},
    { 5,   12,  BV2_STR,  VARIABLE(srISO.pszField05)},
    { 6 + SKIP,  2, BCD_STR, VARIABLE(szDiscard)},
    { 7,   10,   BCD_STR,  VARIABLE(srISO.pszField07)},
 /*  { 7,   14,   BCD_STR,  VARIABLE(srISO.pszField07)},*/
    { 8,   12,   BCD_STR,  VARIABLE(srISO.pszField08)},
    { 9 + SKIP,  2, BCD_STR, VARIABLE(szDiscard)},
    { 10 + SKIP, 2, BCD_STR, VARIABLE(szDiscard)},
    { 11,  6,   BCD_LNG,  (void*) &srISO.lnField11, sizeof(long)},
    { 12,  6,   BCD_STR,  VARIABLE(srISO.pszField12)},
    { 13,  4,   BCD_STR,  VARIABLE(srISO.pszField13)},
    { 14,  4,   BCD_STR,  VARIABLE(srISO.pszField14)},
    { 15,  4,   BCD_STR,  VARIABLE(srISO.pszField15)},
    { 17,  4,   BCD_STR,  VARIABLE(srISO.pszField17)},
    { 18,  4,   BCD_STR,  VARIABLE(srISO.pszField18)},
    { 22,  3,   BCD_STR,  VARIABLE(srISO.pszField22)},
    { 24,  3,   BCD_STR,  VARIABLE(srISO.pszField24)},
    { 25,  2,   BCD_STR,  VARIABLE(srISO.pszField25)},
    { 26,  16,  BIT_BIT,  VARIABLE(srISO.pszField26)},
    { 27,  10,  BV2_STR,  VARIABLE(srISO.pszField27)},
    { 28,  16,  BIT_BIT,  VARIABLE(srISO.pszField28)},
    { 30,  24,  BCD_STR,  VARIABLE(srISO.pszField30)},
    { 31,  50,  AV2_STR,  VARIABLE(srISO.pszField31)},
    { 32,  11,  BV2_STR,  VARIABLE(srISO.pszField32)},
    { 33,  11,  BCD_STR,  VARIABLE(srISO.pszField33)},
    { 35,  37,  COMPUTE,  VARIABLE(srISO.pszField35)},
    { 37,  12,  ASC_STR,  VARIABLE(srISO.pszField37)},
    { 38,  6,   ASC_STR,  VARIABLE(srISO.pszField38)},
    { 39,  2,   ASC_STR,  VARIABLE(srISO.pszField39)},
    { 41,  8,   ASC_STR,  VARIABLE(srISO.pszField41)},
    { 42,  15,  ASC_STR,  VARIABLE(srISO.pszField42)},
    { 43,  40,  ASC_STR,  VARIABLE(srISO.pszField43)},
    { 44,  25,  AV2_STR,  VARIABLE(srISO.pszField44)},
    { 45,  76,  AV2_STR,  VARIABLE(srISO.pszField45)},
    { 47,   8,  VARIANT,  VARIABLE(srISO.pszField47)},
    { 48,  50,  AV3_STR,  VARIABLE(srISO.pszField48)},
    { 52,  64,  BIT_BIT,  VARIABLE(srISO.pszField52)},
    { 53,  16,  BCD_STR,  VARIABLE(srISO.pszField53)},
    { 54,  12,  AV3_STR,  VARIABLE(srISO.pszField54)},
    { 55,  255,  AV3_AV3,  VARIABLE(srISO.pszField55)},
    { 56,  35,  AV2_STR,  VARIABLE(srISO.pszField56)},
    { 57,  12,  BCD_SNZ, VARIABLE(srISO.pszField57)},
    { 60,  0,   VARIANT,  TABLE(srTempVariant60)},
    { 61,  10,  AV3_STR,  VARIABLE(srISO.pszField61)},
    { 62,  50,  AV3_STR,  VARIABLE(srISO.pszField62)},
    { 63,  0,   VARIANT,  TABLE(srTempVariant63)},
    { 64,  16,  BCD_STR,  VARIABLE(srISO.pszField64)},
    { 66,  1,   BCD_STR,  VARIABLE(srISO.pszField66)},
    { 70,  4,   BCD_STR,  VARIABLE(srISO.pszField70)},
    { 74,  10,  BCD_STR,  VARIABLE(srISO.pszField74)},
    { 75,  10,  BCD_STR,  VARIABLE(srISO.pszField75)},
    { 76,  10,  BCD_STR,  VARIABLE(srISO.pszField76)},
    { 77,  10,  BCD_STR,  VARIABLE(srISO.pszField77)},
    { 78,  10,  BCD_STR,  VARIABLE(srISO.pszField78)},
    { 79,  10,  BCD_STR,  VARIABLE(srISO.pszField79)},
    { 80,  10,  BCD_STR,  VARIABLE(srISO.pszField80)},
    { 81,  10,  BCD_STR,  VARIABLE(srISO.pszField81)},
    { 86,  16,  BCD_STR,  VARIABLE(srISO.pszField86)},
    { 87,  16,  BCD_STR,  VARIABLE(srISO.pszField87)},
    { 88,  16,  BCD_STR,  VARIABLE(srISO.pszField88)},
    { 89,  16,  BCD_STR,  VARIABLE(srISO.pszField89)},
    { 90,  42,  BCD_STR,  VARIABLE(srISO.pszField90)},
    { 97,  16,  XBC_STR,  VARIABLE(srISO.pszField97)},
    { 118, 10,  BCD_STR,  VARIABLE(srISO.pszField118)},
    { 119, 16,  BCD_STR,  VARIABLE(srISO.pszField119)},
    { 128 + STOP, 16,   BCD_STR,  VARIABLE(srISO.pszField128)},

};

converters convert_table[] = {
    { asc_to_asc, asc_to_asc },                 /* ASC_ASC */
    { av3_to_av3, av3_to_av3 },                 /* AV3_AV3 */
    { bit_to_bit, bit_to_bit },                 /* BIT_BIT */
    { bcd_to_bcd, bcd_to_bcd },                 /* BCD_BCD */
    { asc_to_bcd, bcd_to_asc },                 /* BCD_ASC */
    { str_to_asc, asc_to_str },                 /* ASC_STR */
    { str_to_bcd, bcd_to_str },                 /* BCD_STR */
    { str_to_bcd, bcd_to_snz },                 /* BCD_SNZ */
    { str_to_av2, av2_to_str },                 /* AV2_STR */
    { str_to_bv2, bv2_to_str },                 /* BV2_STR */
    { str_to_av3, av3_to_str },                 /* AV3_STR */
    { str_to_xbc, xbc_to_str },                 /* XBC_STR */
    { hst_to_bin, bin_to_hst },                 /* BIN_HST */
    { hst_to_bi2, bi2_to_hst },                 /* BI2_HST */
    { hst_to_bi3, bi3_to_hst },                 /* BI3_HST */
    { lng_to_bcd, bcd_to_lng },                 /* BCD_LNG */
    { int_to_bcd, bcd_to_int },                 /* BCD_INT */
    { str_to_bf2, bv2_to_str },                 /* BF2_STR */
    { bi3_to_bi3, bi3_to_bi3 }                  /* BI3_BI3 */
};

/*********************************************************************************************
* @func void | bcd_to_lng |
*       This function is called by the ISO message Engine while
*       packing/unpacking a field, whose conversion is defined
*       as BCD to LONG.
*
* @parm int | inDigits |
*       Number of BCD digits
*
* @end
**********************************************************************************************/
void bcd_to_lng(int inDigits) {
    long int* t_buff;
    unsigned char * tmp;

    get_dst_8583(&tmp);

    t_buff = (long *) tmp;

    bcd_to_asc(inDigits);


    tmp[inDigits] = 0;
    *t_buff = str2long((char *) tmp);

    tmp += sizeof(long int);
    set_dst_8583(tmp);
}

/*********************************************************************************************
* @func void | lng_to_bcd |
*       This function is called by the ISO message Engine while
*       packing/unpacking a field, whose conversion is defined
*       as LONG to BCD.
*
* @parm int | inDigits |
*       Number of BCD digits
*
* @end
**********************************************************************************************/
void lng_to_bcd(int inDigits) {
    long int* t_buff;
    unsigned char buff[16];
    unsigned char * tmp;

    get_src_8583(&tmp);

    t_buff = (long *) tmp;
    long2str((char *) buff, (long) * t_buff);
    pad((char *) buff, (char *) buff, '0', inDigits, RIGHT);

    tmp += sizeof(long int);
    set_src_8583(tmp);

    get_dst_8583(&tmp);
    SVC_DSP_2_HEX((char *) buff, (char *) tmp, inDigits);

    tmp += inDigits / 2;
    set_dst_8583(tmp);
}

/*********************************************************************************************
* @func void | bcd_to_int |
*           This function is called by the ISO message Engine while
*           packing/unpacking a field, whose conversion is defined
*           as BCD to INT.
*
* @parm int | inDigits |
*       Number of BCD digits
*
* @end
**********************************************************************************************/

void bcd_to_int(int inDigits) {
    int* pinBuff;
    unsigned char szLocalBuff[16];

    pinBuff = (int *) tdst_8583;
    tdst_8583 = szLocalBuff;

    bcd_to_asc(inDigits);
    szLocalBuff[inDigits] = 0;
    *pinBuff = atoi((char *) szLocalBuff);
    tdst_8583 = (unsigned char *) pinBuff;
    return;
}

/*********************************************************************************************
* @func void | int_to_bcd |
*           This function is called by the ISO message Engine while
*           packing/unpacking a field, whose conversion is defined
*           as INT to BCD.
*
* @parm int | inDigits |
*       Number of BCD digits
*
* @end
**********************************************************************************************/

void int_to_bcd(int inDigits) {
    int inCount = inDigits;
    int* pinBuff;
    unsigned char szLocalBuff[10];

    pinBuff = (int *) tsrc_8583;
    if (inCount % 2)
        inCount++;
    sprintf((char *) szLocalBuff, SUBSTITUTE_LD, (int) * pinBuff);
    pad((char *) szLocalBuff, (char *) szLocalBuff, '0', (unsigned char) inCount, RIGHT);
    SVC_DSP_2_HEX((char *) szLocalBuff, (char *) tdst_8583, inCount);
    tsrc_8583 += sizeof(int);
    tdst_8583 += inCount / 2;
    return;
}

/*********************************************************************************************
* @func void | bi3_to_bi3 |
*               This function is called by the ISO message Engine while
*               packing/unpacking a field, whose conversion is defined
*               as BI3_BI3. It copies a two bcd count bytes binary string
*               from tsrc_8583 to tdst_8583 including the first two count bytes.
*
* @parm int | inDigits |
*       Maximum field length
*
* @end
**********************************************************************************************/

void bi3_to_bi3(int inDigits) {
    int inCount;

    inCount = inBCD2Int((unsigned char *) tsrc_8583);
    /** /pdebug(("count=%d max=%d", inCount,inDigits)); */
    if (((inCount + 2) > inDigits) || (inCount == 0))
        tdst_8583 = 0;
    else {
        inCount += 2;       /* include the two count bytes */
        while (inCount--)
            *tdst_8583++ = *tsrc_8583++;
    }
    return;
}

/*********************************************************************************************
* @func void | i_put_len_v2 |
*           Store a length in 1 byte. Stores (length div 10) in high order nibble
*           and (length mod 10) in low order nibble. Assumes 0<=n<=99
*
* @parm int | n |
*       Length
*
* @rdesc return values.
* @flag int    | Length
* @end
**********************************************************************************************/

int i_put_len_v2(int n) {
    *tdst_8583++ = (unsigned char) ((n / 10 << 4) | (n % 10));
    return n;
}

/*********************************************************************************************
* @func unsigned char | i_get_asc_to_bcd |
*           Return the binary result of an ASCII digit in the global
*           request buffer. Ex: 32h -> 2
*
* @rdesc return values.
* @flag unsigned char | Binary value
* @end
**********************************************************************************************/

unsigned char i_get_asc_to_bcd() {
    return (unsigned char) (*tsrc_8583++ - '0');
}

/*********************************************************************************************
* @func void | str_to_bf2 |
*               This function is called by the ISO message Engine while
*               packing/unpacking a field, whose conversion is defined
*               as STR to BV2 and padded with 0x0F if odd length.
*               NULL_CH terminated BCD string to 1 byte counted string.
* @parm int | inDigits |
*       Number of BCD digits
*
* @end
**********************************************************************************************/

void str_to_bf2(int inDigits) {
    int inLen;

    /* check if length exceeds max packet size 02/07/96 GS */
    if ((inLen = strlen((char *) tsrc_8583)) > inDigits)
        tdst_8583 = 0;
    else
        max_asc_to_bvf(i_put_len_v2(inLen));
}

/*********************************************************************************************
* @func int | inBCD2Int |
*       Converts a 2 Bytes BCD string to Integer.
*
* @parm char * | pstBCD |
*
* @rdesc Integer value.
* @end
**********************************************************************************************/

int inBCD2Int(unsigned char* pstBCD) {
    int inLen;

    inLen = ((pstBCD[0] >> 4) * 10 + (pstBCD[0] & 0x0F)) * 100;
    inLen += ((pstBCD[1] >> 4) * 10 + (pstBCD[1] & 0x0F));
    return(inLen);
}


/*********************************************************************************************
* @func void | max_asc_to_bvf |
*               ASCII to packed BCD. ASCII string truncated on right if too long.
* @parm int | inDigits |
*       Number of BCD digits
*
* @end
**********************************************************************************************/

void max_asc_to_bvf(int inDigits) {
    SVC_WAIT(1);          /* This WAIT makes the function work - pmk */

    while (inDigits-- > 0) {
        *tdst_8583 = (unsigned char) (i_get_asc_to_bcd() << 4);  /* most significant nibble  */
        if (inDigits > 0) {
            /* more to go               */
            *tdst_8583 |= i_get_asc_to_bcd(); /* least significant nibble */
            inDigits--;
        } else
            *tdst_8583 |= (0x0F);
        tdst_8583++;
    }
}
/*********************************************************************************************
* @func unsigned int | return_variant1 |
*     Used by the ISO Message Engine for processing Variant Type fields.
*     When processing the field tables, the ISO message engine calls this
*     function, then compares the value to the value in the first
*     position of each array element of the variant field table.
*
* @rdesc return values.
* @flag unsigned int |  Returns the Processing Code
* @end
**********************************************************************************************/

unsigned int return_variant1() {
    unsigned char szTemp[2 + 1];

    memset(szTemp, 0, sizeof(szTemp));
    SVC_UNPK4((char *) szTemp, (char *) srISO.pszField03, 1);
    return(atoi((char *) szTemp));
}

/*********************************************************************************************
* @func unsigned int | return_variant2 |
*     Used by the ISO Message Engine for processing Variant Type fields.
*     When processing the field tables, the ISO message engine calls this
*     functions, the compares the value to the value in the second
*     position of each array element of the variant field table.
*
* @rdesc return values.
* @flag unsigned int |  Returns the Message Type Identifier
* @end
**********************************************************************************************/
unsigned int return_variant2() {
    unsigned char szTemp[4 + 1];

    memset(szTemp, 0, sizeof(szTemp));
    SVC_UNPK4((char *) szTemp, (char *) Mti, 2);
    return(atoi((char *) szTemp));
}

/*********************************************************************************************
* @func void |  vdOverLoadISOFDT |
* Changes a field in the base field table.
*
* @parm int | inField |
*       The field number.
*
* @parm field_struct * | srFieldStruct |
*       The new field structure.
*
* @end
**********************************************************************************************/

void vdOverLoadISOFDT(int inField,field_struct* srFieldStruct) {
    srBaseIsoFDT[inField] = *srFieldStruct;
    return;
}

int IFLDTBL_CODE_CHECK(char* a,char* b,short* c,char* d,unsigned char* e) {
    GET_VER(a, b, c, d, e);
    return 1;
}


#endif /* PIP_DEFINED */

#undef IFLDTBL_C

